import java.util.*;

public class TranspositionPuzzle implements State, StateWithCost {
	private String state;
	
	
	public TranspositionPuzzle(String state) {
		if (state == null)
			throw new IllegalArgumentException();
		
		this.state = state;
	}
	
	public void randomize() {
		ArrayList<Character> chars = new ArrayList<>(state.length());
		for (int i = 0; i < state.length(); i++)
			chars.add(state.charAt(i));
		Collections.shuffle(chars);
		StringBuffer sb = new StringBuffer();
		for (Character c : chars)
			sb.append(c);
		state = sb.toString();
	}
	
	public Iterable<State> getNeighbors() {
		ArrayList<State> neighbors = new ArrayList<>();
		for (int i = 0; i < state.length(); i++)
			for (int j = i + 1; j < state.length(); j++)
				neighbors.add(swap(i, j));
		return neighbors;
	}
	
	public Map<StateWithCost,Double> getNeighborsWithCost() {
		Map<StateWithCost,Double> neighbors = new HashMap<>();
		for (int i = 0; i < state.length(); i++)
			for (int j = i + 1; j < state.length(); j++)
				neighbors.put(swap(i, j), new Double(j - i));
		return neighbors;
	}

	public String toString() {
		return state.toString();
	}

	public boolean equals(Object obj) {
		if (!(obj instanceof TranspositionPuzzle))
			return false;
		if (obj == this)
			return true;
		return state.equals(((TranspositionPuzzle)obj).state);
	}

	public int hashCode() {
		return state.hashCode();
	}
	
	private TranspositionPuzzle swap(int i, int j) {
		StringBuffer sb = new StringBuffer();
		int k = 0;
		for (; k < i; k++)
			sb.append(state.charAt(k));
		sb.append(state.charAt(j));
		for (k++; k < j; k++)
			sb.append(state.charAt(k));
		sb.append(state.charAt(i));
		for (k++; k < state.length(); k++)
			sb.append(state.charAt(k));
		return new TranspositionPuzzle(sb.toString());
	}

}